# 张量学习
import torch
import numpy as np

# 生成一个两行三列的一个0到1均匀分布的矩阵
# x = torch.range(2, 3)
# # 3行4列的正态分布矩阵
# x = torch.randn(3, 4)
#
# # 2行3列的全0数组
# x = torch.zeros(2, 3)
# x = torch.ones(2, 3)


# 直接创建一个tensor,并指定数据类型
# x = torch.tensor([6, 2], dtype=torch.float32)
# print(x.type())
# 转换类型
# x = x.type(torch.int64)
# print(x)


# # tensor与ndarray数据类型转换
# # 生成一个2行3列的正态分布的随机数
# a = np.random.randn(2, 3)
# # 通过ndarray 转化为张量 tensor
# X1 = torch.from_numpy(a)
# #
# print(X1)

"""
张量运算
"""
# x1 = torch.rand(2, 3)
# x2 = torch.rand(2, 3)
# print(x1)
# print(x2)
# # 对应下标相加
# x3 = x1 + x2
# # 所有元素都会+3，广播
# x4 = x1 + 3
# # 等价于
# x1.add(3)
# # 以上都是值传递
# # 下是地址传递
# x1.add_(3)
# # 运行过后，x1值已经改变了
#
#
# # tensor改变形状
# x1 = x1.view(3, 2)
# # 展开数据
# # -1 自动计算，转化为一个数组集合，集合内每个数组都只有1个元素
# x1.view(-1, 1)
# # x1 均值,返回的任然是一个tensor
# x1.mean()
# # 直接返回一个数值
# x1.mean().item()


"""
张量的自动微分
将Torch.Tensor属性.requires_grad 设置为true；
pytorch将开始耿总对比张量的所有操作。
完成计算后，可以先用.backward()并自动计算所有梯度
该张量的梯度将累加到.grad属性中
"""
# 这个张量会被跟踪所有运算
x = torch.ones(2, 2, requires_grad=True)
y = x + 2
# print(y)
# print(y.grad_fn)
z = y * y + 3
out = z.mean()
# print(out)
# 计算微分
out.backward()
print(x.grad)
